#include "CLongScreenShotInApp.h"
#include <QQuickItem>
#include <QQmlApplicationEngine>
#include <QImage>
#include <QDir>
#include <QPainter>

CLongScreenShotInApp::CLongScreenShotInApp(QQmlEngine *engine, QObject *parent)
    : QObject{parent},m_pEngine{engine}
{
    setSavePath("./longScreenShotInApp");
}

bool CLongScreenShotInApp::start()
{
    //0.重置状态，清理截图缓存目录，model
    reset();

    //1.从 Engine 中找到 Window
    m_pCurrentWindow = findActiveWindw(m_pEngine);
    if (!m_pCurrentWindow) {
        qWarning() << "None QWindow!";
        return false;
    }

    //2.从 Window 中找到滚动区控件
    m_pCurrenScrollArea = findScrollArea(m_pCurrentWindow);
    if (!m_pCurrenScrollArea) {
        //@TODO 没找到滚动区  直接截图结束
        QSharedPointer<QImage> result = grabWindow(m_pCurrentWindow);
        QString fileName = QString("%1/%2").arg(m_strSavePath, "longScreenshot.png");
        if (!result->save(fileName)) {
            qWarning() << "title.png save failed:" << fileName;
        } else {
            qInfo() << "Save success:" << fileName;
            m_nLongScreenHeight += result->height();
            appendToModel(fileName);
        }
        setFinished(true);
        return true;
    }

    //3.滚动截取4页，需要继续调用 scrollAndGrab 截图
    scrollAndGrab(4);

    return true;
}

void CLongScreenShotInApp::scrollAndGrab(int pageCount)
{
    if (isFinished())
        return ;
    scrollAndGrab(m_pCurrentWindow, m_pCurrenScrollArea, m_strSavePath, pageCount);
}

bool CLongScreenShotInApp::isFinished()
{
    return m_bFinished;
}

QStringListModel *CLongScreenShotInApp::model()
{
    return &m_modelImages;
}

QString CLongScreenShotInApp::save(QString fileName)
{
    if (0 == m_modelImages.rowCount()) {
        qWarning() << "No image!!!";
        return "";
    }

    QSharedPointer<QImage> resultLongScreenshot = QSharedPointer<QImage>(new QImage(m_pCurrentWindow->width(),
                                                                                    m_nLongScreenHeight,
                                                                                    QImage::Format_ARGB32_Premultiplied));
    QPainter painter(resultLongScreenshot.data());
    int offsetY = 0;
    foreach (QString fileName, m_modelImages.stringList()) {
        qDebug() << "fileName:" << fileName;
        QImage image(fileName);
        if (image.isNull()) {
            qWarning() << "img Null:" << fileName;
            continue ;
        }

        painter.drawImage(0,offsetY,image);
        offsetY += image.height();
        qDebug() << "offsetY:" << offsetY;
    }

    QString resultFileName = QString("%1/%2").arg(m_strSavePath, fileName);
    if (!resultLongScreenshot->save(resultFileName)) {
        qWarning() << "Save failed:" << resultFileName;
        return "";
    } else {
        qInfo() << "Save success:" << resultFileName;
    }

    return resultFileName;
}

void CLongScreenShotInApp::reset()
{
    m_pCurrentWindow = nullptr;
    m_pCurrenScrollArea = nullptr;
    m_nContentIndex = 0;
    m_nLongScreenHeight = 0;
    m_modelImages.removeRows(0, m_modelImages.rowCount());
    setFinished(false);
    clearDirectory(m_strSavePath);
}

QQuickWindow *CLongScreenShotInApp::findActiveWindw(QQmlEngine *engine)
{
    //1.用 QQmlApplicationEngine::load,可以直接从 rootObjects 中找到 Window
    QQmlApplicationEngine *pAppEngine = qobject_cast<QQmlApplicationEngine *>(m_pEngine);
    if (pAppEngine) {
        qDebug() << "rootObj:" << pAppEngine->rootObjects();
        foreach (QObject *obj, pAppEngine->rootObjects()) {
            if (obj->inherits("QQuickWindow")) {
                QQuickWindow *pWindow = qobject_cast<QQuickWindow *>(obj);
                if (pWindow && pWindow->isActive())
                    return pWindow;
            }
        }
    }
    //2. 用 QQuickView 创建的 Window 通过 engine->parent() 获取
    else
    {
        if (engine->parent()->inherits("QQuickWindow")) {
            QQuickWindow *pWindow = qobject_cast<QQuickWindow *>(engine->parent());
            if (pWindow && pWindow->isActive())
                return pWindow;
        }
    }

    return nullptr;
}

QQuickItem *CLongScreenShotInApp::findScrollArea(QWindow *window)
{
    qDebug() << "FindScrollArea...";
    QList<QQuickItem *> listItems = window->findChildren<QQuickItem *>(); //像 QQuickFlickable 是Qt私有类，所以不能直接查找
    //    qDebug() << "listItems:" << listItems;
    QStringList scrollAreaClassNames;
    scrollAreaClassNames << "QQuickFlickable" << "QQuickListView" << "QQuickGridView";
    QQuickItem *pCurrentScrollAreaItem = nullptr;
    foreach (QQuickItem *pItem, listItems) {
        if (scrollAreaClassNames.contains(pItem->metaObject()->className())) {
            qDebug() << pItem->objectName() << pItem->metaObject()->className() << " " << pItem->isVisible()
                     << pItem->x() << pItem->y() << pItem->mapToScene(QPointF(0,0)) << pItem->property("");
            QPointF ptPosition = pItem->mapToScene(QPointF(0,0));
            int contentHeight = pItem->property("contentHeight").toInt();
            if ((ptPosition.x() >= 0 && ptPosition.x() < (window->width() * 0.5))
                && pItem->height() < contentHeight) {
                qInfo() << "FindListView:" << pItem << pItem->objectName();
                pCurrentScrollAreaItem = pItem;
                break ;
            }
        }
    }

    if (nullptr == pCurrentScrollAreaItem) {
        qWarning() << "Window no scorll area item:" << scrollAreaClassNames;
        return nullptr;
    }

    if (!pCurrentScrollAreaItem->property("contentY").isValid()) {
        qWarning() << "Window no scorll area item:" << scrollAreaClassNames;
        return nullptr;
    }

    return pCurrentScrollAreaItem;
}

QSharedPointer<QImage> CLongScreenShotInApp::grabWindow(QWindow *window)
{
    QQuickWindow *pQuickWindow = qobject_cast<QQuickWindow *>(window);
    if (pQuickWindow) {
        QImage* image = new QImage(pQuickWindow->grabWindow());
        return QSharedPointer<QImage>(image);
    } else {
        qWarning() << "Can't grab window!!!" << window;
        return QSharedPointer<QImage>();
    }
}

void CLongScreenShotInApp::scrollAndGrab(QWindow *window, QQuickItem *scrollAreaItem, const QString &savePath, int pageCount)
{
    //1.获取 scrollAreaItem 在 sence 的位置
    QPointF ptPosition = scrollAreaItem->mapToScene(QPointF(0,0));
    int startY = ptPosition.y();
    int endY = startY + scrollAreaItem->height();

    //2.边滚动边截图
    int contentY = scrollAreaItem->property("contentY").toInt();
    int contentHeight = scrollAreaItem->property("contentHeight").toInt();
    int itemHeight = scrollAreaItem->height();

    for (int i = 0; i < pageCount; i++) {
        int realHeight = qMin(itemHeight, contentHeight - contentY); //获取实际可用的图像高度

        // 截取当前区域的图像
        QSharedPointer<QImage> image = grabWindow(window);
        QImage tmpImage = image->copy(QRect(0, startY, image->width(), realHeight));

        //1.首张截图，处理 titile, appBar
        if (0 == m_modelImages.rowCount())
        {
            //2.保存标题区域
            QString titleFileName = QString("%1/%2").arg(savePath, "title.png");
            QImage titleImage = image->copy(QRect(0, 0, image->width(), startY));
            if (!titleImage.save(titleFileName)) {
                qWarning() << "title.png save failed:" << titleFileName;
            } else {
                qInfo() << "Save success:" << titleFileName;
                m_nLongScreenHeight += titleImage.height();
                appendToModel(titleFileName);
            }

            //3.保存导航区域
            QString appBarFileName = QString("%1/%2").arg(savePath, "appBar.png");
            QImage appBarImage = image->copy(QRect(0, endY, image->width(), image->height() - endY));
            if (!appBarImage.save(appBarFileName)) {
                qWarning() << "appBar.png save failed:" << appBarFileName;
            } else {
                qInfo() << "Save success:" << appBarFileName;
                m_nLongScreenHeight += appBarImage.height();
                appendToModel(appBarFileName);
            }
        }

        // 保存滚动区截图
        QString fileName = QString("%1/%2-content.png").arg(savePath).arg(m_nContentIndex, 4, 10, QChar('0'));
        if (!tmpImage.save(fileName)) {
            qWarning() << "Stop grab!!! Save failed:" << fileName;
            return ;
        }

        insertToModel(m_modelImages.rowCount() - 1, fileName);

        qDebug() << "Save img:" << fileName;

        //滚动
        contentY += itemHeight;
        scrollAreaItem->setProperty("contentY", contentY);
        m_nContentIndex++;
        m_nLongScreenHeight += tmpImage.height();

        if (contentY + itemHeight > contentHeight) {
            qInfo() << "At end:" << fileName;
            scrollAreaItem->setProperty("contentY", contentHeight - itemHeight);
            setFinished(true);
            break;
        }
    }
}

void CLongScreenShotInApp::setSavePath(QString path)
{
    m_strSavePath = path;
    // 创建目录
    QDir saveDir(m_strSavePath);
    if (!saveDir.exists()) {
        if (!saveDir.mkpath(".")) {
            qWarning() << "Failed to create save directory:" << m_strSavePath;
        }
    }
}

void CLongScreenShotInApp::setFinished(bool ok)
{
    if (ok == m_bFinished)
        return ;

    m_bFinished = ok;
    emit finished();
}

void CLongScreenShotInApp::clearDirectory(const QString &dirPath)
{
    QDir dir(dirPath);

    // 判断目录是否存在
    if (!dir.exists()) {
        qWarning() << "Directory does not exist:" << dirPath;
        return;
    }

    // 获取目录中的所有文件
    QStringList fileList = dir.entryList(QDir::Files);

    // 遍历文件列表，删除每个文件
    foreach (const QString& fileName, fileList) {
        QString filePath = dirPath + "/" + fileName;
        if (QFile::remove(filePath)) {
            qDebug() << "Removed file:" << filePath;
        } else {
            qWarning() << "Failed to remove file:" << filePath;
        }
    }
}

void CLongScreenShotInApp::appendToModel(const QString &fileName)
{
    m_modelImages.insertRow(m_modelImages.rowCount());
    m_modelImages.setData(m_modelImages.index(m_modelImages.rowCount() - 1), getAbsolutePath(fileName));
}

void CLongScreenShotInApp::insertToModel(int index, const QString &fileName)
{
    m_modelImages.insertRow(index);  // 在末尾插入一行
    m_modelImages.setData(m_modelImages.index(index), getAbsolutePath(fileName));
}

QString CLongScreenShotInApp::getAbsolutePath(const QString &fileName)
{
    QFileInfo fileInfo(fileName);
    if (fileInfo.isRelative()) {
        QDir currentDir = QDir::current();
        return currentDir.absoluteFilePath(fileName);
    } else {
        return fileInfo.absoluteFilePath();
    }
}

QString CLongScreenShotInApp::titleImageFileName()
{
    return QString("%1/%2").arg(m_strSavePath,"title.png");
}

QString CLongScreenShotInApp::appBarImageFileName()
{
    return QString("%1/%2").arg(m_strSavePath,"appBar.png");
}
